package cn.edu.jxau.util;

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * 利用数组实现栈
 * 1.每项操作的用时都和集合大小无关
 * 2.空间需求总是不超过集合大小乘以一个常数
 * 3.扩容的时间复杂度是O(n)
 * @author 付大石
 */
public class ArrayStack<T> extends Stack<T> {
    
    private T[] arr;
    private int size;
    private static final int INIT_CAPACITY = 10;

    public ArrayStack() {

        arr = (T[]) new Object[INIT_CAPACITY];
        size = 0;
    }

    @Override
    public Iterator<T> iterator() {

        return new Iterator<T>() {

            private int cursor = size - 1;

            @Override
            public boolean hasNext() {
                return cursor >= 0;
            }

            @Override
            public T next() {
                if (!hasNext()) {
                    throw new NoSuchElementException("迭代器所处位置无元素");
                }
                return arr[cursor--];
            }
        };
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public T peek() {
        if(isEmpty()) {
            return null;
        }
        return arr[size - 1];
    }

    @Override
    public T pop() {

        T item = arr[--size];
        arr[size] = null;
        if (size * 4 < arr.length) {
            resize(arr.length / 2);
        }
        return item;
    }

    @Override
    public void push(T item) {

        if (size == arr.length) {
            resize(arr.length * 2);
        }
        arr[size++] = item;
    }

    private void resize(int newCapacity) {

        if (newCapacity < INIT_CAPACITY) { // 避免缩减得太小
            return;
        }
        System.out.printf("resize to %d\n", newCapacity);
        T[] tempArr = (T[]) new Object[newCapacity];
        for (int i = 0; i < size; i++) {
            tempArr[i] = arr[i];
        }
        arr = tempArr;
    }

    @Override
    public String toString() {

        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("stack size=").append(size).append("\t");
        stringBuilder.append("[");
        if (size == 0) {
            stringBuilder.append("]");
        } else {
            for (int i = size - 1; i >= 0; i--) {
                stringBuilder.append(arr[i]).append(",");
            }
            stringBuilder.deleteCharAt(stringBuilder.length()-1).append("]");
        }
        return stringBuilder.toString();
    }
}
